
////////////////////////////////////////////////////////////////////////////
//	File Name: TVector.inl		Last modification at : 2002-10-10 13:49:04
//	Copyright 1999-2002 Microsoft Corporation. All Rights Reserved.
//
//	Author:      Rong Xiao
//	Email :      t-rxiao@microsoft.com
//
//	Description : 
//
//	Revision History: 
//
////////////////////////////////////////////////////////////////////////////


// @cmember Constructor, read data from string
template <typename T>
inline TVector<T>::TVector(const int nDim, const char * valStr)
{	
	initSize(nDim);
	m_IsMemoryRef=false;
	m_data=Allocate(GetDim());
	Zero();
	::istrstream ins(valStr);
	for(int i=0; i<m_Size; i++) 
		ins>>m_data[i];
}

// @cmember Copy Constructor
template <typename T>
inline TVector<T>::TVector(const TVector<T>& Vect)
{
	initSize(Vect.m_Dim);

	if ( Vect.IsRef() ) 
		Array2Vect(Vect.GetPtr(),Vect.GetDim(),true);
	else {
		m_IsMemoryRef=false;
		m_data=Allocate(GetDim());
		TArrayCpy(m_data, Vect.m_data, m_Dim);
	}
}

// @cmember Release the memory if needed.
template <typename T>
inline void TVector<T>::Destroy()
{
	if ( false==m_IsMemoryRef )
		DestroyPtr(m_data);
	m_data = NULL;
}


// @mfunc Resize the memory of vector
template <typename T>
inline T* TVector<T>::NewSize(const int nDim, const bool bInit)
{
	assert(nDim >= 0 );

	if ( bInit==true) {
		if(m_Dim != nDim || m_data == NULL) {
			Destroy();
			m_Dim=nDim;
			m_IsMemoryRef=false;
			m_data=Allocate(GetDim());
		}
		if ( m_data )
			Zero();
	}
	else {
		if ( m_Dim == nDim && m_data!=NULL ) 
			return m_data;
		T* pDst;
		int dimCpy, dimTail;

		pDst= Allocate(nDim);
		if ( !pDst )
			return 0;

		dimCpy=TMin(m_Dim, nDim);
		dimTail=nDim-dimCpy;

		TArrayCpy( pDst, m_data, dimCpy);
		if ( dimTail > 0 )
			TArrayInit( pDst+dimCpy, dimTail );
		delete[] m_data;
		m_Dim=nDim;
		m_data=pDst;
	}
	return m_data;
}

// @mfunc Set a val to whole Vector
template <typename T>
inline void TVector<T>::Set(const T val)
{
	assert(m_data != NULL);

	int i;
	for(i=0; i<m_Dim; i++)
	{
		m_data[i] = val;
	}
}

// @cmember set an element's value
template <typename T>
inline void TVector<T>::SetAt(int nDim, T NewValue)
{
	assert(m_data);
	assert(nDim<m_Dim);
	assert(nDim>=0);

	m_data[nDim]=NewValue;
}

// @cmember get an element's value
template <typename T>
inline T TVector<T>::GetAt(int nDim) const
{
	assert(m_data);
	assert(nDim<m_Dim);
	assert(nDim>=0);
	
	return m_data[nDim];
}


//random all the element in vector
template<typename T>
inline void TVector<T>::random(void)	
{
	srand( (unsigned)time( NULL ) );
	T *p=m_data;
	int i;
	for(i=0;i<m_Dim;i++)
		(*p++)=rand();
}




// @cmember Operator [], used to access the element of vector
//		This is const version, It is necessary.
template<typename T>
inline const T& TVector<T>::operator[](int nDim) const
{	
	assert(m_data);
	assert(nDim<m_Dim);
	assert(nDim>=0);
	
	return m_data[nDim];	
}


// @cmember Operator [], used to access the element of vector
template<typename T>
inline T& TVector<T>::operator[](int nDim)
{	
	assert(m_data);
	assert(nDim<m_Dim);
	assert(nDim>=0);
	
	return m_data[nDim];
}

// @mfunc Copy from another vector
template <typename T>
inline TVector<T>& TVector<T>::operator=( 
			const TVector<T>& ref		//@parm	Input vector to copy 
)
{
	assert(ref.m_data != NULL);

	if(m_Dim != ref.m_Dim )
	{
		NewSize(ref.m_Dim);
	}
	else if(m_data == NULL) {
		m_IsMemoryRef=false;
		m_data=Allocate(GetDim());
	}

	TArrayCpy(m_data, ref.m_data, m_Dim );

	return *this;
}


// @mfunc Assign the vector with the same element
template<typename T>
inline TVector<T>& TVector<T>::operator=(const T& scale)
{
	assert( m_data != NULL);

    int i;

	for(i=0; i<m_Dim; i++)	{
		m_data[i] = scale;
	}
	return *this;
}

// @mfunc Add of vector.
template <typename T>
inline TVector<T> TVector<T>::operator+(const TVector<T>& ref) const
{
	assert(m_data != NULL);
	assert(ref.m_Dim == m_Dim);

	T* ptr=Allocate(m_Dim);

	for(int i=0; i<m_Dim; i++)	{
		ptr[i] = m_data[i] + ref.m_data[i];
	}
	return TVector<T>(ptr,m_Dim);
}


// @cmember increase all Vector elements
template <typename T>
inline TVector<T> TVector<T>::operator+(const T increment) const
{
	assert( m_data != NULL);

	int i;
	T* ptr=Allocate(m_Dim);
    
    for(i=0; i<m_Dim; i++)	{
		ptr[i] = m_data[i] + increment;
	}
	return TVector<T>(ptr,m_Dim);
}


// @mfunc minus of vector.
template <typename T>
inline TVector<T> TVector<T>::operator-(const TVector<T>& ref) const
{
	assert(m_data != NULL);
	assert(ref.m_Dim == m_Dim );

	T* ptr=Allocate(m_Dim);
	for(int i=0; i<m_Dim; i++)	{
		ptr[i] = m_data[i] - ref.m_data[i];
	}
	return TVector<T>(ptr, m_Dim);
}


// @cmember decrease all Vector elements
template <typename T>
inline TVector<T> TVector<T>::operator-(const T decrement) const
{
	assert( m_data != NULL);

	int i;
	T* ptr=Allocate(m_Dim);
	for(i=0; i<m_Dim; i++)	{
		ptr[i] = m_data[i] - decrement;
	}
	return TVector<T>(ptr, m_Dim);

}


// @mfunc Multiple of Vector.
template <typename T>
inline T TVector<T>::operator*(const TVector<T>& ref) const
{
	assert(m_Dim == ref.m_Dim);	//illegal multiple
	assert(m_data != NULL);
	assert(ref.m_data != NULL);

	T sum;
    sum=0;

    for ( int i=0; i<m_Dim; i++ ) 
        sum += m_data[i] * ref.m_data[i];

	return sum;
}

template <typename T>
inline TVector<T> TVector<T>::operator*(const TMatrix<T>& ref) const
{
	assert(m_Dim == ref.GetRows());	//illegal multiple
	assert(m_data != NULL);

	int nDim;
	nDim=ref.GetCols();

	T* ptr=Allocate(nDim);
	T sum;

	for(int i=0; i<nDim; i++)	{
		sum=0;
		for ( int j=0; j<m_Dim; j++) {
			sum+=m_data[j]*ref.GetAt(j,i);
		}
		ptr[i]=sum;
	}
	return TVector<T>(ptr,nDim);
}

// @mfunc Mutiple of Vector with a numeric.
template <typename T>
inline TVector<T> TVector<T>::operator*(const T scale) const
{
	assert( m_data != NULL);

	int i;
	T* ptr=Allocate(m_Dim);
	for(i=0; i<m_Dim; i++)	{
		ptr[i] = m_data[i] * scale;
	}

	return TVector<T>(ptr,m_Dim);
}

// @cmember Vector divide a numeric
template <typename T>
inline TVector<T> TVector<T>::operator/(const T scale) const
{
	assert( m_data != NULL);
	assert( scale );

	int i;

	T* ptr=TFloatVector::Allocate(m_Dim);
	for(i=0; i<m_Dim; i++)	
		ptr[i] = m_data[i] / scale;
	
	return TVector<T>(ptr,m_Dim);
}

// @cmember add a vector to this vector
template <typename T>
void TVector<T>::operator+=(const TVector<T>& ref)
{
	assert( m_data != NULL);
	assert(	m_Dim==ref.m_Dim);

	int i;
	for(i=0; i<m_Dim; i++)	{
		m_data[i] = m_data[i] + ref.m_data[i];
	}
}

// @cmember add a numeric to all the element
template <typename T>
void TVector<T>::operator+=(const T incriment)
{
	assert( m_data != NULL);
	
	int i;
	for(i=0; i<m_Dim; i++)	{
		m_data[i] = m_data[i] + incriment;
	}
}

// @cmember subtract a vector from this vector
template <typename T>
void TVector<T>::operator-=(const TVector<T>& ref)
{
	assert( m_data != NULL);
	assert(	m_Dim==ref.m_Dim);

	int i;
	for(i=0; i<m_Dim; i++)	{
		m_data[i] = m_data[i] - ref.m_data[i];
	}
}

// @cmember subtract a numeric from all the element
template <typename T>
void TVector<T>::operator-=(const T decriment)
{
	assert( m_data != NULL);
	
	int i;
	for(i=0; i<m_Dim; i++)	{
		m_data[i] = m_data[i] - decriment;
	}
}


// @cmember multiple a numeric to all the element
template <typename T>
void TVector<T>::operator*=(const T scale)
{
	assert( m_data != NULL);
	
	int i;
	for(i=0; i<m_Dim; i++)	{
		m_data[i] = m_data[i] * scale;
	}
}

// @cmember multiple a numeric to all the element
template <typename T>
void TVector<T>::operator*=(const TMatrix<T>& ref)
{
	assert( m_data != NULL);
	assert ( m_Dim==ref.GetRows());
	T* pDst;
	int nDim;
	nDim=ref.GetCols();
	pDst=TFloatVector::Allocate(nDim);

	T sum;
	for(int i=0; i<nDim; i++)	{
		sum=0;
		for ( int j=0; j<m_Dim; j++) {
			sum+=m_data[j]*ref.GetAt(j,i);
		}
		pDst[i]=sum;
	}
	NewSize(nDim);
	delete[] m_data;
	m_data=pDst;
}

// @cmember each elements divide a numeric
template <typename T>
void TVector<T>::operator/=(const T scale)
{
	assert( m_data != NULL);
	assert( scale );
	
	int i;
	for(i=0; i<m_Dim; i++)	{
		m_data[i] = m_data[i] / scale;
	}
}

// @mfunc Operator of equal
template <typename T>
inline bool TVector<T>::operator == (const TVector<T>& ref) const
{
	if(m_Dim != ref.m_Dim)
		return false;

    return (memcmp((void*)m_data,(void*)ref.m_data,m_Dim*sizeof(T)))==0;
	//add end
}

template <typename T>
inline int TVector<T>::Compare (const TVector<T>& ref) const
{
	int nDim;

	nDim = TMin(m_Dim, ref.GetDim());

	for ( int i=0; i<nDim; i++ ) {
		if (  m_data[i] < ref[i] )
			return -1;
		if (  m_data[i] > ref[i] )
			return 1;
	}
	return m_Dim-ref.GetDim();
}

template <typename T>
inline TVector<T>::operator TCharVector() const
{
	if(typeid(T) == typeid(char))
		return *this;

    char* ptr=TCharVector::Allocate(m_Dim);

	for(int i=0; i<m_Dim; i++)		{
		ptr[i] = (char)m_data[i];
	}
	
    return TVector<char>(ptr,m_Dim);
}

template <typename T>
inline TVector<T>::operator TShortVector() const
{
	if(typeid(T) == typeid(short))
		return *this;

    short* ptr= TShortVector::Allocate(m_Dim);
	for(int i=0; i<m_Dim; i++)		{
		ptr[i] = (short)m_data[i];
	}
	return TVector<short>(ptr,m_Dim);
}

template <typename T>
inline TVector<T>::operator TIntVector() const
{
	if(typeid(T) == typeid(int))
		return *this;

	int *ptr=TIntVector::Allocate(m_Dim);
	
	for(int i=0; i<m_Dim; i++)		{
		ptr[i] = (int)m_data[i];
	}

	return TVector<int>(ptr,m_Dim);
}

template <typename T>
inline TVector<T>::operator TByteVector() const
{
	if(typeid(T) == typeid(unsigned char))
		return *this;

    BYTE* ptr=TByteVector::Allocate(m_Dim);
	for(int i=0; i<m_Dim; i++)		{
		ptr[i] = (BYTE)m_data[i];
	}
	return TVector<BYTE>(ptr,m_Dim);
}

template <typename T>
inline TVector<T>::operator TUShortVector() const
{
	if(typeid(T) == typeid(unsigned short))
		return *this;
	
	unsigned short* ptr= TUShortVector::Allocate(m_Dim);
	for(int i=0; i<m_Dim; i++)		{
		ptr[i] = (unsigned short)m_data[i];
	}
	return TVector<unsigned short>(ptr, m_Dim);
}

template <typename T>
inline TVector<T>::operator TUIntVector() const
{
	if(typeid(T) == typeid(unsigned int))
		return *this;

    unsigned int	*ptr=TUIntVector::Allocate(m_Dim);
	
	for(int i=0; i<m_Dim; i++)		{
		ptr[i] = (unsigned int)m_data[i];
	}

	return TVector<unsigned int>(ptr, m_Dim);
}

template <typename T>
inline TVector<T>::operator TFloatVector() const
{
	if(typeid(T) == typeid(float))
		return *this;

    float* ptr=TFloatVector::Allocate(m_Dim);
	for(int i=0; i<m_Dim; i++)		{
		ptr[i] = (float)m_data[i];
	}
	return TVector<float>(ptr, m_Dim);
}

template <typename T>
inline TVector<T>::operator TDoubleVector() const
{
	if(typeid(T) == typeid(double))
		return *this;
	
	double *ptr=TDoubleVector::Allocate(m_Dim);
	for(int i=0; i<m_Dim; i++)		{
		ptr[i] = (double)m_data[i];
	}
	return TVector<double>(ptr, m_Dim);
}

//conver the vector to matrix row vector
template <typename T>
inline TVector<T>::operator TMatrix<T>() const
{
	T* ptr=Allocate(m_Dim);

	TArrayCpy(ptr,m_data, m_Dim);

	return TMatrix<T>(ptr, 1, m_Dim);
}

// @cmember swap row , base 0
template <typename T>
inline void TVector<T>::SwapDim(int nDim1,int nDim2)
{
    assert(m_data);
	assert(nDim1< m_Dim && nDim2<m_Dim && nDim1>=0 && nDim2>=0);
	if(nDim1==nDim2)
		return ;

    T temp;

    temp=m_data[nDim1];
    m_data[nDim1]=m_data[nDim2];
    m_data[nDim2]=temp;
}

// @cmember swap row , base 0
template <typename T>
inline int TVector<T>::DelAt(int index)
{
    assert(m_data);
	assert (index< m_Dim && index>=0 );

	if (index>= m_Dim && index<0 )
		return -1;

	T* pData;
	pData=Allocate(m_Dim-1);
	SwapDim(index,m_Dim-1);
	m_Dim--;
	TArrayCpy(pData,m_data, m_Dim);
	delete[] m_data;
	m_data=pData;
	return 0;
}


// @cmember return a sub vector, base 0
template <typename T>
inline TVector<T> TVector<T>::GetSubVector(int nDimLeft, int nDim) const
{
	assert(m_data);
	assert(nDimLeft< m_Dim && nDimLeft+nDim<=m_Dim && nDimLeft>=0 && nDim>0);
	
	T* ptr=Allocate(nDim);
	TArrayCpy(ptr, m_data+nDimLeft, nDim);

    return TVector<T>(ptr,nDim);
}

// @cmember return a sub vector, base 0
template <typename T>
inline int TVector<T>::SetSubVector(TVector<T>& subVect, int nDimLeft)
{
	assert(m_data);
	int nDim=subVect.GetDim();
	
	if ( (nDimLeft<0) || (nDim+nDimLeft>m_Dim) ) {
		assert(false);
		return -1;
	}
	
	TArrayCpy(m_data+nDimLeft,subVect.GetPtr(), nDim);

    return 0;
}

// @cmember write down the vector
template <typename T>
inline int TVector<T>::Write(const char* szFname, bool bBinary) const
{
	assert(szFname);
	std::ofstream Fout;
	
	if ( bBinary==true ) Fout.open(szFname, std::ios::binary);
	else Fout.open(szFname);

    return Write(Fout,bBinary);
}

template <typename T>
inline int TVector<T>::Write(std::ostream& Fout, bool bBinary) const
{
    assert(Fout);
    if (!Fout) return -1;
	
	assert(GetPtr() != NULL);
	T* pSrc=m_data;
	int nDim=GetDim();

	if ( bBinary==true ) {
		Fout.write((const char*)&nDim, sizeof(int));
		Fout.write((const char*)pSrc,nDim*sizeof(T));
	}
	else {
		Fout << nDim  << std::endl;	
		TArrayWrite(Fout,pSrc, nDim);
	}
	return 0;
}    

// @cmember read the matrix 
template <typename T>
inline int TVector<T>::Read(const char* szFname, bool bBinary)
{
    assert(szFname);
	std::ifstream Fin;
	if (bBinary==true)
		Fin.open(szFname,std::ios::binary);
	else
		Fin.open(szFname);

    return Read(Fin, bBinary);  
}

template <typename T>
inline int TVector<T>::Read(std::istream& Fin, bool bBinary)
{
    if (!Fin) return -1;

    int nDim;

	if ( true==bBinary ) {
		Fin.read((char*)&nDim,sizeof(int));
		NewSize(nDim);

		Fin.read((char*)GetPtr(),nDim*sizeof(T));
	}
	else {
		Fin >> nDim;
		NewSize(nDim);
		TArrayRead(Fin,GetPtr(), nDim);
	}
	return 0;
}

template <typename T>
inline int TVector<T>::ReadRow(const char* szMat, int iRow)
{
    assert(szMat);
	std::ifstream Fin(szMat,std::ios::binary );
    return ReadRow(Fin, iRow);  
}

template <typename T>
inline int TVector<T>::ReadRow(std::istream& Fin, int iRow)
{
	int nRows, nCols;
	int nTSize;
	int nRet=0;

    if ( ReadTMatrixHeader( Fin, nTSize, nRows, nCols) == -1 ) {
		std::cout << "Matrix Data Header has been destroyed!" << std::endl;    
		nRet= -1;
	}
	else
	{
		if ( nTSize != sizeof(T) ) {
			std::cout << "Data type mismatch!" << std::endl;
			nRet= -1;
		}
		else
		{
			//Check index;
			if ( iRow<0 || iRow>=nRows )
				nRet= -1;
		}
	}

	if ( nRet==0 && NewSize(nCols) )
	{
		Fin.seekg(iRow*nCols*sizeof(T)+3*sizeof(int), std::ios_base::beg);
		Fin.read((char*)m_data,nCols*sizeof(T));
		nRet=0;
	}
	else
		nRet=-1;
	return nRet;
}

// @func output of the vector as string
template <typename T>
inline std::ostream & operator << (std::ostream& os, const TVector<T>& vect)
{
	vect.Write(os,false);
	return os;
}

// @func input vector, as the sequence of " Rows, Cols, ele[0][0], ele[0][1], ... ele[N][N]
template<typename T>
inline std::istream & operator >> (std::istream& is, TVector<T>& vect)
{
	vect.Read(is,false);
	return is;
}


//display function for debug, print out the vector content in debug output window
template<typename T>
inline void TVector<T>::Print()
{
#ifdef _DEBUG
	T *p=m_data;
	TRACE("\nDim=%d\n",m_Dim);
	for(int i=0;i<m_Dim;i++)	{
		TRACE("%f",(double)(*p++));
	}
	TRACE("\n");
#endif
}

template<typename T>
inline int TVector<T>::CopyData(const TVector<T>& refVect)
{
	if ( m_Dim<=0 || refVect.m_Dim<=0 ) 
		return 0;
	int iCopy;
	iCopy=TMin(m_Dim,refVect.m_Dim);
	TArrayCpy(m_data,refVect.m_data,iCopy);
	return iCopy;
}
	
template <typename T>
inline TVector<T>& TVector<T>::Array2Vect(const T *pData, int nDim, bool bRef)
{
	assert(pData);
	assert(nDim>0);

    if ( m_data !=NULL )
        Destroy();

	m_Dim=nDim;
	m_data=(T*)pData;
    m_IsMemoryRef=bRef;

	return *this;
}

// @cmember use a array for data directly
template <typename T>
inline TVector<T>& TVector<T>::ImportData(const T *pData, int nDim)
{
	assert(pData);
	assert(nDim>0);

	NewSize(nDim);
	TArrayCpy(m_data,pData,m_Dim);
	return *this;
}

template <typename T>
inline TVector<T>& TVector<T>::ImportData(const std::vector<T> vect)
{
	int nDim=vect.size();
	NewSize(nDim);
	for ( int i=0; i<nDim; i++ ) 
		m_data[i]=vect[i];
	return *this;
}

// @cmember Is this vector equal zero vector? 
template <typename T>
inline bool TVector<T>::IsZero() const
{
	assert(m_data!=NULL);
	assert(m_Dim>0);
	
    T *p=m_data;
    for ( int i=0; i<m_Dim; i++ ) {
        if ( TAbs(*p) > _ZERO )
            return false;
    }
	return true;
}

// @cmember return sum of all elements
template <typename T>
inline double TVector<T>::Sum(void) const
{
	assert(m_data);

	double sum=0;
	for(int i=0;i<m_Dim;i++)
		sum+=m_data[i];
	return sum;
	
}

// @cmember return mean of columns
template <typename T>
inline double TVector<T>::Mean(void) const
{
	assert(m_data);
	assert(m_Dim>0);

    return Sum()/m_Dim;
}

// @cmember return sum of all elements
template <typename T>
inline T TVector<T>::TSum(void) const
{
	assert(m_data);

	T sum=0;
	for(int i=0;i<m_Dim;i++)
		sum+=m_data[i];
	return sum;
	
}

// @cmember return mean of columns
template <typename T>
inline T TVector<T>::TMean(void) const
{
	assert(m_data);
	assert(m_Dim>0);

    return Sum()/m_Dim;
}

// @cmember Get OuterProduct
template <typename T>
inline TVector<T> TVector<T>::DirectProduct(const TVector<T>& ref) const
{
	assert ( m_data );
	assert ( m_Dim==ref.GetDim() );

	T* ptr=Allocate(m_Dim);
	
	for ( int i=0; i<m_Dim; i++ ) 
		ptr[i]=m_data[i]*ref[i];

	return TVector<T>(ptr,m_Dim);
}

// @cmember Get OuterProduct
template <typename T>
inline TMatrix<T> TVector<T>::DescartesProduct(const TVector<T>& ref) const
{
	assert ( m_data );
	int nRows,nCols, index;
	nCols=ref.GetDim();
	nRows=m_Dim;

	T* ptr=Allocate(nRows*nCols);

	index=0;
	for ( int iRow=0; iRow<nRows; iRow++)
		for ( int iCol=0; iCol<nCols; iCol++)
			ptr[index++]=m_data[iRow]*ref[iCol];

	return TMatrix<T>(ptr, nRows, nCols);
}

// Compute ABS vector
template <typename T>
inline TVector<T> TVector<T>::abs(void) const
{
	assert ( m_data && m_Dim>=0 );
	
	T* ptr=Allocate(m_Dim);
	
	for ( int i=0; i<m_Dim; i++ )
		ptr[i]=TAbs(m_data[i]);

	return TVector<T>(ptr, m_Dim);
}

// @cmember return 2-norm distance of two vector 
template <typename T>
inline double TVector<T>::GetDistance2(const TVector<T>& ref) const
{   
	assert( m_data != NULL);
	assert(	m_Dim==ref.m_Dim);

    double sum;
    T tmp;

    T *pSrc, *pDst;
    pSrc=m_data;
    pDst=ref.m_data;

    sum=0;
    for ( int i=0; i<m_Dim; i++ ) {
        tmp=(*pSrc++)-(*pDst++);
        sum+=tmp*tmp;
    }
    return sum;
}

// @cmember return 2-norm distance of two vector 
template <typename T>
inline T TVector<T>::TGetDistance2(const TVector<T>& ref) const
{   
	assert( m_data != NULL);
	assert(	m_Dim==ref.m_Dim);

    T sum;
    T tmp;

    T *pSrc, *pDst;
    pSrc=m_data;
    pDst=ref.m_data;

    sum=0;
    for ( int i=0; i<m_Dim; i++ ) {
        tmp=(*pSrc++)-(*pDst++);
        sum+=tmp*tmp;
    }
    return sum;
}

// @cmember return the distance of two vector 
template <typename T>
inline double TVector<T>::GetDistance(const TVector<T>& ref) const
{
	assert( m_data != NULL);
	assert(	m_Dim==ref.m_Dim);

    return sqrt(GetDistance2(ref));
}

// @cmember return 2-norm the vector 
template <typename T>
inline double TVector<T>::GetNorm2(void) const
{   
	assert( m_data != NULL);
	
    double sum;
    T tmp;

    T *pSrc;
    pSrc=m_data;

    sum=0;
    for ( int i=0; i<m_Dim; i++ ) {
        tmp=(*pSrc++);
        sum+=tmp*tmp;
    }
    return sum;
}

// @cmember return 2-norm the vector 
template <typename T>
inline T TVector<T>::TGetNorm2(void) const
{   
	assert( m_data != NULL);
	
    T sum;
    T tmp;

    T *pSrc;
    pSrc=m_data;

    sum=0;
    for ( int i=0; i<m_Dim; i++ ) {
        tmp=(*pSrc++);
        sum+=tmp*tmp;
    }
    return sum;
}

// @cmember return the distance of two vector 
template <typename T>
inline double TVector<T>::GetNorm() const
{
	assert( m_data != NULL);
	
    return sqrt(GetNorm2());    
}

// @cmember Get the variance 
template <typename T>
inline double TVector<T>::GetVariance(void) const
{
	return sqrt( GetNorm2()/m_Dim - TSquare(Mean()) );
}

// @cmember set the vector norm to 1 ( or 0 for zeros )
template <typename T>
inline TVector<double> TVector<T>::Normalize(void) const
{
    assert( m_data != NULL);

    double dNorm;

	double *ptr=TVector<double>::Allocate(m_Dim);
   
    dNorm=GetNorm();
    if (TAbs(dNorm)<_ZERO) 
        return 0;
    
    for ( int i=0; i<m_Dim; i++ ) 
        ptr[i]=((double)m_data[i])/dNorm;

    return TVector<double>(ptr,m_Dim);
}

template <typename T> 
inline TVector<T> TVector<T>::ReScale(T tLow, T tHigh) const
{
	assert(tHigh>tLow);
	T tmin;
	double dScale;
	T* ptr=Allocate(m_Dim);


	tmin=Min();
	dScale=Max()-tmin;
	if (dScale<TEPSILON) {
		TArraySet(ptr,tLow,m_Dim);
	}
	else {
		dScale=(tHigh-tLow)/dScale;
		for ( int i=0; i<m_Dim; i++) {
			ptr[i]=T ( (m_data[i]-tmin)*dScale+tLow );
		}
	}
	return TVector<T>(ptr,m_Dim);
}

template <typename T> 
inline TVector<T> TVector<T>::DupReverse(void) const
{
	T* ptr=Allocate(m_Dim);
	TArrayCpyReverse(ptr,m_data,m_Dim);
	return TVector<T>(ptr,m_Dim);
}

//reverse the vect
template <typename T> 
inline TVector<T>& TVector<T>::Reverse(void)
{
	TArrayReverse(m_data,m_Dim);
	return *this;
}

//return the max value of vect
template <typename T> 
inline T TVector<T>::Max(void) const
{
	return TArrayMax(m_data,m_Dim);
}

//return the min value of vect
template <typename T> 
inline T TVector<T>::Min(void) const
{
	return TArrayMin(m_data,m_Dim);
}

//return the max value pos of vect
template <typename T> 
inline int TVector<T>::MaxPos(void) const
{
	return TArrayMaxPos(m_data,m_Dim);
}

//return the min value pos of vect
template <typename T> 
inline int TVector<T>::MinPos(void) const
{
	return TArrayMinPos(m_data,m_Dim);
}


template <typename T> 
inline TVector<T>& TVector<T>::Shuffle()
{
	assert ( m_data && m_Dim>0 );
	CRand utRand;
	int j;
	for ( int i=m_Dim-1; i>0; i--) {
		j=utRand.iRand(0,i);
		TSwap(m_data[i], m_data[j]);
	}
    return *this;
}

template <typename T> 
inline TVector<T>& TVector<T>::QSort(int iStyle)
{
	TQSort(m_data,m_Dim,iStyle);
	return *this;
}

//Do not modify the pArray contents, just update index
template <typename T> 
inline TVector<int> TVector<T>::QIndexSort(int iStyle) const
{
	int* ptr;

	ptr=TQIndexSort(m_data,m_Dim,iStyle);

	return TVector<int>(ptr,m_Dim);
}

//Do bubble sort nStep, the first nStep minimal element will be put ahead
//default sort all array.
template <typename T> 
inline TVector<T>& TVector<T>::BubbleSort(int nStep, int iStyle)
{
	TBubbleSort(m_data,m_Dim,nStep,iStyle);
	return *this;
}

//Just bubble sort the index
template <typename T> 
inline TVector<int> TVector<T>::BubbleIndexSort( int nStep, int iStyle) const
{
	int* ptr;
	ptr=TBubbleIndexSort(m_data,m_Dim,nStep,iStyle);

	return TVector<int>(ptr,m_Dim);
}

//Required the array is sorted (ascending)
template <typename T> 
inline int TVector<T>::BSearch( T key, int iStyle) const
{
	return TBSearch(m_data,m_Dim,key,iStyle);
}

template <typename T> 
inline int TVector<T>::CountPositives() const
{ 
	int iCount=0; 
	for ( int i=0; i<m_Dim; i++ ) 
		if ( m_data[i]>0 ) iCount++;
	return iCount;
}

template <typename T> 
inline int TVector<T>::CountZeros() const
{
	int iCount=0; 
	for ( int i=0; i<m_Dim; i++ ) 
		if ( m_data[i]==0 ) iCount++;
	return iCount;
}

template <typename T> 
inline int TVector<T>::CountNegatives() const
{ 
	int iCount=0; 
	for ( int i=0; i<m_Dim; i++ ) 
		if ( m_data[i]<0 ) iCount++;
	return iCount;
}
